﻿using System;
using Expect.Core.Errors;
using Expect.Core.Interfaces;

namespace Expect.Core.Helpers
{    
    /// <summary>
    /// Helper methods for specification resolution
    /// </summary>
    public static class ResolveSpecification
    {
        /// <summary>
        /// Look for a specification implementation
        /// </summary>
        public static bool Resolve(this IExecutionContext context, SpecificationDefinition specification)
        {
            if (specification.ClassType == null)
            {
                if (string.IsNullOrEmpty(specification.ClassName))
                {
                    if (!string.IsNullOrEmpty(specification.Name) && specification.Name != specification.Id)
                    {
                        string specname = context.NameProvider.ElementName(specification.Name);
                        Type t = context.Catalog.GetSpecification(specname);
                        if (t != null && t.IsASpecificationImplementation())
                        {
                            specification.ClassType = t;
                        }
                    }
                }
                else
                {
                    specification.ClassType = context.Catalog.GetSpecification(specification.ClassName);
                    if (specification.ClassType == null)
                    {
                        //CurrentSpecification.Status.Success = false;
                        specification.Status.AddError(
                            ElementNotFoundError.Class(specification.ClassName, ElementKind.Specification));
                        return false;
                    }
                    if (!specification.ClassType.IsSubclassOf(typeof(AbstractSpecImplementation)))
                    {
                        specification.Status.Success = false;
                        specification.Status.AddError(
                            ElementNotFoundError.Specification(specification.ClassName));
                        //throw new ArgumentException(string.Format("Test implementation {1} must inherit from {0}", typeof(AbstractSpecImplementation).FullName, Specification.ClassName));
                    }
                }
            }

            if (specification.ClassType != null && !context.ResolveOnly)
            {
                specification.InitializeImplementation(context);

                if (specification.Implementation != null)
                {
                    specification.Implementation.Context = context;
                    return true;
                }
            }

            return false;
        }
    }
}
